//=================================================
// X_NC_http.c
// 2015-03-27 
//=================================================
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
//#include <unistd.h>
#include <time.h>
//#include <fcntl.h>
//#include <termios.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

// Nabton Control Protocol
#define ON_NABTON_SID    1
#define ON_DELAY         2
#define ON_STEPPER_CTRL  4

int create_tcp_socket();
char *get_ip(char *host);
char *build_get_query(char *host, char *page);
void usage();
char* httpClient(char* host, char* page);
 
#define HOST "coding.debuntu.org"
#define PAGE "/"
#define PORT 80
#define USERAGENT "HTMLGET 1.0"

//===============================
void delay(int t)
//===============================
{
  t = t*1000; // convert to ms
  usleep(t);
} 
//===============================
void writeDebug()
//===============================
{
  FILE  *out;
  out = fopen("debug.nab","w");
  fprintf(out,"%d",g_count);
  fclose(out);
}
//===============================
void handleServerResponse(char* ht)
//===============================
{
	char  line[128],key[32];
    int   itemp,k,val1,val2,val3,answer = 0;
    int   i;
    int   c = 0;
    char  **arr = NULL;

    c = split(ht, ':', &arr);

    printf("found %d tokens.\n", c);

    for (i = 0; i < c; i++)
    {
      //printf("string #%d: %s\n", i, arr[i]);
      strcpy(line,arr[i]);
          if(silent==0)printf("%s\n",line);
          sscanf(line,"%s",key);
          if(strstr(key,"NABTON_SID")    != NULL) 
          {
			  sscanf(line,"%s %d",key,&val1);
			  answer = 1; 
			  nb_sid = val1;
		  }
          if(strstr(key,"DELAY")     != NULL) 
          {
			  answer = 1; 
			  sscanf(line,"%s %d %d",key,&val1,&val2);
			  on[ON_DELAY_VAL]  = 1; 
			  on[ON_DELAY_UNIT]  = 1; 
			  value[ON_DELAY_VAL]  = val1;
			  value[ON_DELAY_UNIT] = val2;   
	      }
          if(strstr(key,"STEPPER_CTRL")  != NULL) 
          {
			  answer = 1; 
			  sscanf(line,"%s %d %d %d",key,&val1,&val2,&val3);
			  on[ON_STEPPER_DIR] = 1; 
			  on[ON_STEPPER_STEPS] = 1; 
			  on[ON_STEPPER_SPEED] = 1; 
			  value[ON_STEPPER_DIR] = val1;
			  value[ON_STEPPER_STEPS] = val2;
			  value[ON_STEPPER_SPEED] = val3;
		  }
       }
       //sendArduino(1,"+"); // Confirmation
       if(answer == 1)
       {
		  //serialFlush();
		  if(silent==0)printf("GWY: Server Message sid: %d\n",nb_sid);
          msg[0] = NABTON_DATA_ACK;
          msg[1] = (nb_sid&0xff);
          itemp = nb_sid >> 8;
          msg[2] = (itemp&0xff);
          k = 3;
          for(i=0;i<100;i++)
          {
		      if(on[i] != 0)
		      {
				 if(silent==0)printf("GWY: MSG:%d Value: %d\n",i,value[i]);
			     msg[k] = i;
			     msg[k+1] = value[i];
			     k = k + 2;
		      }
	      }
	      msg[k] = 0;
	      if(silent==0)printf("GWY: Total Message size: %d\n",k);
	      k++;
          sendArduino(k,msg);
       }
       else
        if(silent==0)printf("GWY: No Server Message - check if SID is defined in database\n");
     
}
//===============================
void sendAckToArduino()
//===============================
{
	msg[0] = NABTON_DATA_ACK;
    msg[1] = (nb_sid&0xff);
    int itemp = nb_sid >> 8;
    msg[2] = (itemp&0xff);
    sendArduino(3,msg);
}
//===============================
void readConfig()
//===============================
{
  FILE  *in,*out;
  char  line[128];
  char temps[12];

  in = fopen("config.nab","r");
  if(in == NULL)
    {
      strcpy(arh_url,   "213.67.148.190");
      strcpy(arh_page,  "nabton/NDSServer/NDSCollector.php");
      strcpy(arh_dev,   "/dev/ttyACM0");
      
      if(silent==0)printf("Create config file\n");
      out = fopen("config.nab","w");
      fprintf(out,"URL:   %s\n",arh_url);
      fprintf(out,"PAGE:  %s\n",arh_page);
      fclose(out);
    }
  else
    {
      if(silent==0)printf("Open config file\n");
      while (fgets(line,sizeof line,in) != NULL)
          {
            if(strstr(line,"URL:") != NULL)sscanf(line,"%s %s",temps,arh_url);
            if(strstr(line,"PAGE:") != NULL)sscanf(line,"%s %s",temps,arh_page);
          }
      fclose(in);
    } 
}
//===============================
char* httpClient(char* host, char* page)
//===============================
{
  struct sockaddr_in *remote;
  int sock;
  int tmpres;
  char *ip;
  char *get;
  char buf[BUFSIZ+1];

  //usage(host,page);
 
  sock = create_tcp_socket();
  ip = get_ip(host);
  //fprintf(stderr, "IP is %s\n", ip);
  remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
  remote->sin_family = AF_INET;
  tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr)));
  if( tmpres < 0)  
  {
    perror("Can't set remote->sin_addr.s_addr");
    exit(1);
  }else if(tmpres == 0)
  {
    fprintf(stderr, "%s is not a valid IP address\n", ip);
    exit(1);
  }
  remote->sin_port = htons(PORT);
 
  if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){
    perror("Could not connect");
    exit(1);
  }
  get = build_get_query(host, page);
  //fprintf(stderr, "Query is:\n<<START>>\n%s<<END>>\n", get);
 
  //Send the query to the server
  int sent = 0;
  while(sent < strlen(get))
  {
    tmpres = send(sock, get+sent, strlen(get)-sent, 0);
    if(tmpres == -1){
      perror("Can't send query");
      exit(1);
    }
    sent += tmpres;
  }
  //now it is time to receive the page
  memset(buf, 0, sizeof(buf));
  int htmlstart = 0;
  char * htmlcontent;
  while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){
    if(htmlstart == 0)
    {
      /* Under certain conditions this will not work.
      * If the \r\n\r\n part is splitted into two messages
      * it will fail to detect the beginning of HTML content
      */
      htmlcontent = strstr(buf, "\r\n\r\n");
      if(htmlcontent != NULL){
        htmlstart = 1;
        htmlcontent += 4;
      }
    }else{
      htmlcontent = buf;
    }
    if(htmlstart){
      strcpy(g_buf,htmlcontent);
    }
 
    memset(buf, 0, tmpres);
  }
  if(tmpres < 0)
  {
    perror("Error receiving data");
  }
  free(get);
  free(remote);
  free(ip);
  close(sock);
  return g_buf;
}
//===============================
void usage(char* host, char* page)
//===============================
{
  fprintf(stderr, "USAGE: htmlget host=%s [page=%s]\n",host,page);
}
 
//=============================== 
int create_tcp_socket()
//===============================
{
  int sock;
  if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
    perror("Can't create TCP socket");
    exit(1);
  }
  return sock;
}
 
//=============================== 
char *get_ip(char *host)
//===============================
{
  struct hostent *hent;
  int iplen = 15; //XXX.XXX.XXX.XXX
  char *ip = (char *)malloc(iplen+1);
  memset(ip, 0, iplen+1);
  if((hent = gethostbyname(host)) == NULL)
  {
    printf("ip:%s\n",host);
    herror("Can't get IP");
    exit(1);
  }
  if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
  {
    perror("Can't resolve host");
    exit(1);
  }
  return ip;
}
 
char *build_get_query(char *host, char *page)
{
  char *query;
  char *getpage = page;
  char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
  if(getpage[0] == '/'){
    getpage = getpage + 1;
    fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page, getpage);
  }
  // -5 is to consider the %s %s %s in tpl and the ending \0
  query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5);
  sprintf(query, tpl, getpage, host, USERAGENT);
  return query;
}
//===============================
int main(int argc, char **argv)
//===============================
{   
  int i,value = 9999, nc_state;
  time_t tm;
  struct tm *ltime;

  char res[120],stemp[120],sys[240];
    
  silent = 1;    
  if(argc == 2)
  {
    if(strstr(argv[1],"-d") != NULL) 
     silent = 0;
  }
  
 
  init(); 
  while(1)
  {
      int go = 0;
      if(inToken())  go = readSerial();
     // if(outToken()) go = writeSerial();
      if(go == 1)
      {
         g_count++;
         writeDebug();

         printf("float %d\n",nb_float);
         if(nb_float < 1 || nb_float > 6)nb_float = 2;
         if(nb_nodata == 0 && nb_float == 1)sprintf(sys,"?sid=%d&data=%.1f",nb_sid,nb_data);
         if(nb_nodata == 0 && nb_float == 2)sprintf(sys,"?sid=%d&data=%.2f",nb_sid,nb_data);
         if(nb_nodata == 0 && nb_float == 3)sprintf(sys,"?sid=%d&data=%.3f",nb_sid,nb_data);
         if(nb_nodata == 0 && nb_float == 4)sprintf(sys,"?sid=%d&data=%.4f",nb_sid,nb_data);
         if(nb_nodata == 0 && nb_float == 5)sprintf(sys,"?sid=%d&data=%.5f",nb_sid,nb_data);
         if(nb_nodata == 0 && nb_float == 6)sprintf(sys,"?sid=%d&data=%.6f",nb_sid,nb_data);
         if(nb_nodata == 1)sprintf(sys,"?sid=%d\"",nb_sid);
  
         strcpy(stemp,arh_page);
         strcat(stemp,sys);
         if(silent==0)printf("GWY: %s\n",stemp);
         char* html = httpClient(arh_url,stemp);
         handleServerResponse(html);
      }

	  if(go == 2) // Unknown message
      {
		  if(silent==0)printf("GWY: Unknown message from Arduino\n");
		  sendAckToArduino();
	  }
	  
	  if(go == 3) // Error from Arduino
      {
		  if(silent==0)printf("GWY: Error message processed from Arduino\n");
		  sendAckToArduino();
	  }
	  if(go == 4) // Log from Arduino
      {
		  if(silent==0)printf("GWY: Log message processed from Arduino\n");
		  sendAckToArduino();
	  }
  }
           
  close(tty_fd);
  return EXIT_SUCCESS;
}
